/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 * 用于创建显示进程，引用温湿度和压力，显示至屏幕上。
 * Change Logs:
 * Date           Author       Notes
 * 2021-07-23     wyj          1.0.0
 * 2021-09-04     wyj          1.0.1  将温湿压三个参数集中在此处读取，并加入修正因子，和其设置函数。
 * 2022-04-02     wyj          1.0.6  显示版本号。
 * 2022-05-14     wyj          1.0.7  开机延时N（s）并显示倒计时
 * 2022-05-14     wyj          1.0.8  增加网络状态显示
 * 2022-06-20     wyj          1.1.0增加修正温度为0时，采用外部温湿压传感器
 */
#ifndef APPLICATIONS_DISPLAY_DISPLAY_C_
#define APPLICATIONS_DISPLAY_DISPLAY_C_

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include <string.h>
#include <stdio.h>
#include <GLOBAL/version.h>
#include "ssd1306.h"
#include "am2305/am2305.h"
#include "IO/io.h"
#include "HONEYWELL_PRES_SPI/pres.h"
#include <easyflash.h>
#include <NET/net.h>

#define DBG_TAG "display"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
int16_t temp_calibration_factor = 0;
int32_t pres_calibration_factor = 0;
int16_t humi_calibration_factor = 0;

#define POWER_ON_DELAY              3                     //  开机延时140s

void get_environment_true_value(int16_t *temp_true, int16_t *humi_true, int32_t *pres_true)
{
    int16_t temp;
    int32_t pres;
    int16_t humi;
    temp = *temp_true;
    humi = *humi_true;
    pres = *pres_true;
    if((temp==0) && (pres==0) && (humi==0))              //输入的值都为0，使用内部传感器
    {
        get_temp_humi(0, &temp, &humi);
        pres = get_pressure_and_temp();
    }

    *temp_true = temp + temp_calibration_factor;
    *pres_true = pres + pres_calibration_factor;
    *humi_true = humi + humi_calibration_factor;
}
void calibration_init(void)
{

    int t_cal_f_len = ef_get_env_blob("t_cal_f", &temp_calibration_factor, sizeof(int16_t), 0);
    if (t_cal_f_len == 0)
    {
        temp_calibration_factor = 0;
    }
    int h_cal_f_len = ef_get_env_blob("h_cal_f", &humi_calibration_factor, sizeof(int16_t), 0);
    if (h_cal_f_len == 0)
    {
        humi_calibration_factor = 0;
    }
    int p_cal_f_len = ef_get_env_blob("p_cal_f", &pres_calibration_factor, sizeof(int32_t), 0);
    if (p_cal_f_len == 0)
    {
        pres_calibration_factor = 0;
    }
    LOG_D("t_cal_f is set to:%d", temp_calibration_factor);
    LOG_D("h_cal_f is set to:%d", humi_calibration_factor);
    LOG_D("p_cal_f is set to:%d", pres_calibration_factor);
}
void set_t_cal_f(float factorx)
{
    if ((factorx < -5) && (factorx > 5))
    {
        LOG_W("t factorx if over range!!");
        return;
    }
    temp_calibration_factor = (int16_t) (factorx * 10);
    ef_set_env_blob("t_cal_f", &temp_calibration_factor, sizeof(int16_t));
    //LOG_D("t_cal_f is set to:%d",temp_calibration_factor);
}

void set_h_cal_f(float factorx)
{
    if ((factorx < -5) && (factorx > 5))
    {
        LOG_W("h factorx if over range!!");
        return;
    }
    humi_calibration_factor = (int16_t) (factorx * 10);
    ef_set_env_blob("h_cal_f", &humi_calibration_factor, sizeof(int16_t));
    //LOG_D("h_cal_f is set to:%d",humi_calibration_factor);
}

void set_p_cal_f(float factorx)
{
    if ((factorx < -5) && (factorx > 5))
    {
        LOG_W("p factorx if over range!!");
        return;
    }
    pres_calibration_factor = (int32_t) (factorx * 1000);
    ef_set_env_blob("p_cal_f", &pres_calibration_factor, sizeof(int32_t));
    //LOG_D("p_cal_f is set to:%d",pres_calibration_factor);
}

float get_t_cal_f(void)
{
    float factorx;
    int t_cal_f_len = ef_get_env_blob("t_cal_f", &temp_calibration_factor, sizeof(int16_t), 0);
    if (t_cal_f_len == 0)
        {
            temp_calibration_factor = 0;
        }
    factorx = ((float)temp_calibration_factor)/10.0;
    LOG_D("t_cal_f :%d",temp_calibration_factor);
    return factorx;

}

float get_h_cal_f(void)
{
    float factorx;
    int h_cal_f_len = ef_get_env_blob("h_cal_f", &humi_calibration_factor, sizeof(int16_t), 0);
        if (h_cal_f_len == 0)
        {
            humi_calibration_factor = 0;
        }
    factorx = ((float)humi_calibration_factor)/10.0;
    LOG_D("t_cal_f :%d",humi_calibration_factor);
    return factorx;
}

float get_p_cal_f(void)
{
    float factorx;
    int p_cal_f_len = ef_get_env_blob("p_cal_f", &pres_calibration_factor, sizeof(int32_t), 0);
    if (p_cal_f_len == 0)
    {
        pres_calibration_factor = 0;
    }
    factorx = ((float)pres_calibration_factor)/1000.0;
    LOG_D("t_cal_f :%d",pres_calibration_factor);
    return factorx;
}

static void diaplay_entry(void *parameter)
{
    int16_t temp;
    int32_t pres;
    uint16_t humi;
    char version[11];
    uint16_t display_cnt = 0, i;
    uint8_t io_status = 0, iox_status, display_update = 0;
    char temp_temp[6] = "xx.x ";
    char pres_temp[11] = "xxx.xxxkpa";

    sprintf(version,"ver:%s",VERSION);
    ssd1306_Fill(Black);
    ssd1306_SetCursor(2, 0);
    ssd1306_WriteString("waiting measure!", Font_7x10, White);
    ssd1306_UpdateScreen();
    rt_thread_mdelay(10000);                //等待温湿度第一次测量结果
    ssd1306_Fill(Black);
    ssd1306_SetCursor(2, 0);
    ssd1306_WriteString("temp: ", Font_7x10, White);
    ssd1306_SetCursor(2, 10);
    ssd1306_WriteString("humi: ", Font_7x10, White);
    ssd1306_SetCursor(2, 20);
    ssd1306_WriteString("pres: ", Font_7x10, White);
    ssd1306_SetCursor(2, 40);
    ssd1306_WriteString("IO: 00000000", Font_7x10, White);
    ssd1306_SetCursor(2, 50);
    ssd1306_WriteString(version, Font_7x10, White);
    ssd1306_UpdateScreen();
    while (1)
    {
        display_cnt++;
        if ((display_cnt % 20) == 0)
        {
            get_environment_true_value(&temp, &humi, &pres);
            //温度显示
            temp_temp[0] = temp / 100 + 48;
            temp_temp[1] = temp / 10 % 10 + 48;
            temp_temp[3] = temp % 10 + 48;
            temp_temp[4] = 'C';
            ssd1306_SetCursor(42, 0);
            ssd1306_WriteString(temp_temp, Font_7x10, White);
            //湿度显示
            temp_temp[0] = humi / 100 + 48;
            temp_temp[1] = humi / 10 % 10 + 48;
            temp_temp[3] = humi % 10 + 48;
            temp_temp[4] = '%';
            ssd1306_SetCursor(42, 10);
            ssd1306_WriteString(temp_temp, Font_7x10, White);
            //压力显示
            pres_temp[0] = pres / 100000 + 48;
            pres_temp[1] = pres / 10000 % 10 + 48;
            pres_temp[2] = pres / 1000 % 10 + 48;
            pres_temp[4] = pres / 100 % 10 + 48;
            pres_temp[5] = pres / 10 % 10 + 48;
            pres_temp[6] = pres % 10 + 48;
            ssd1306_SetCursor(42, 20);
            ssd1306_WriteString(pres_temp, Font_7x10, White);

            if(net_is_connected())                  //网络已连接
            {
                ssd1306_SetCursor(42, 30);
                ssd1306_WriteString("net:ON", Font_7x10, White);
            }
            else {
                ssd1306_SetCursor(42, 30);
                ssd1306_WriteString("net:OFF", Font_7x10, White);
            }

            ssd1306_UpdateScreen();
            LOG_D("temp:%d,humi:%d,pres", temp, humi, pres);
        }
        else if ((display_cnt % 2) == 0)
        {
            for (i = 0; i < 8; i++)
            {

                iox_status = get_io_status(i);
                if ((io_status & (1 << i)) != (iox_status << i))
                {
                    ssd1306_SetCursor(30 + i * 7, 40);
                    if (iox_status)
                        ssd1306_WriteString("1", Font_7x10, White);
                    else
                    {
                        ssd1306_WriteString("0", Font_7x10, White);
                    }
                    io_status &= (~(1 << i));
                    io_status |= (iox_status << i);
                    LOG_D("IO status update:%x", io_status);
                    display_update = 1;
                }
            }
            if (display_update)
            {
                ssd1306_UpdateScreen();
                display_update = 0;
            }

        }

        //如果想在循环中加任何其他状态显示，可在此处加入
        rt_thread_mdelay(200);
    }
}
void display_count_down_delay(uint16_t delay_s)
{
    char power_on_delay_c[11];
    while(delay_s--)
    {
        rt_sprintf(power_on_delay_c,"delay:%d",delay_s);
        ssd1306_Fill(Black);
        ssd1306_SetCursor(2, 0);
        ssd1306_WriteString(power_on_delay_c, Font_7x10, White);
        ssd1306_UpdateScreen();
        rt_thread_mdelay(1000);
    }
}
int display_init(void)
{
    ssd1306_Init();
    am2305_start();
    calibration_init();
    display_count_down_delay(POWER_ON_DELAY);                   //开机延迟
    rt_thread_t dispaly_tid = rt_thread_create("display", diaplay_entry, RT_NULL, 1024, 26, 20);
    /* 创建成功则启动线程 */
    if (dispaly_tid != RT_NULL)
    {
        rt_thread_startup(dispaly_tid);
    }
    else
    {
        LOG_E("display create failed!");
    }
    return 0;
}

//INIT_APP_EXPORT(display_init);
#endif /* APPLICATIONS_DISPLAY_DISPLAY_C_ */
